package encaps.utils.rendering;

import encaps.resources.Response;
import encaps.utils.html.HTMLElement;
import encaps.utils.html.HTMLElementSequence;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.DataConversionException;
import org.jdom.Element;

/**
 * Interface of parser which builds HTML code from XML document. The interface
 * is package-visible.
 */
public class EntityParser implements Parser {

    private final Map<String, FieldFactory> fieldFactories;

    public EntityParser() {

        fieldFactories = new HashMap<String, FieldFactory>();

        FieldFactory buttonFactory = new ButtonFactory();
        fieldFactories.put(Response.BUTTON, buttonFactory);

        FieldFactory headerFactory = new HeaderFactory();
        fieldFactories.put(Response.HEADER, headerFactory);

        FieldFactory smallHeaderFactory = new SmallHeaderFactory();
        fieldFactories.put(Response.SMALL_HEADER, smallHeaderFactory);

        FieldFactory imageFactory = new ImageFactory();
        fieldFactories.put(Response.IMAGE, imageFactory);

        FieldFactory linkFactory = new LinkFactory();
        fieldFactories.put(Response.LINK, linkFactory);

        FieldFactory passwordFieldFactory = new PasswordFieldFactory();
        fieldFactories.put(Response.PASSWORD, passwordFieldFactory);

        FieldFactory textFieldFactory = new TextFieldFactory();
        fieldFactories.put(Response.STRING, textFieldFactory);

        FieldFactory textAreaFactory = new TextAreaFactory();
        fieldFactories.put(Response.TEXT, textAreaFactory);

        FieldFactory hiddenTextFieldFactory = new HiddenTextFieldFactory();
        fieldFactories.put(Response.HIDDEN, hiddenTextFieldFactory);

        FieldFactory commentSectionFactory = new CommentSectionFactory();
        fieldFactories.put(Response.COMMENT_SECTION, commentSectionFactory);

        FieldFactory radioControlFactory = new RadioControlFactory();
        fieldFactories.put(Response.RADIO_CONTROL, radioControlFactory);

        FieldFactory selectFactory = new SelectFactory();
        fieldFactories.put(Response.SELECT, selectFactory);

        FieldFactory multiSelectFactory = new MultiSelectFactory();
        fieldFactories.put(Response.MULTISELECT, multiSelectFactory);

        FieldFactory javascriptButtonFactory = new JavascriptButtonFactory();
        fieldFactories.put(Response.JSBUTTON, javascriptButtonFactory);

        FieldFactory javascriptTextInputFactory = new JavascriptTextInputFactory();
        fieldFactories.put(Response.JSTINPUT, javascriptTextInputFactory);

        FieldFactory imageButtonFactory = new ImageButtonFactory();
        fieldFactories.put(Response.IMAGEBUTTON, imageButtonFactory);

        FieldFactory imageLinkFactory = new ImageLinkFactory();
        fieldFactories.put(Response.IMAGELINK, imageLinkFactory);

        FieldFactory lineBreakFactory = new LineBreakFactory();
        fieldFactories.put(Response.LINE_BREAK, lineBreakFactory);
    }

    /**
     * Renders XML element to HTML code which can be included into web page.
     *
     * @param e data in XML format to render that contains text value
     * with/without control.
     * @return HTMLElement with HTML code.
     */
    public HTMLElement renderToHTML(Element response) {
        HTMLElementSequence result = new HTMLElementSequence();
        Element e = response.getChild(Response.ENTITY);
        if (e != null) {
            Boolean edit;
            try {
                edit = e.getAttribute(Response.EDIT).getBooleanValue();
            } catch (DataConversionException ex) {
                edit = false;
            }

            List fields = e.getChildren(Response.FIELD);
            for (Object obj : fields) {
                Element fieldElement = (Element) obj;
                String type = fieldElement.getChildTextTrim(Response.TYPE);
                FieldFactory factory = fieldFactories.get(type);
                HTMLElement field = factory.renderField(fieldElement, edit);
                result.addContent(field);
            }
        }

        return result;
    }
}
